package com.example.demo.web;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author topCombine
 * <p>
 * redis测试
 * 1. 六种数据类型
 * 2. 两种持久化方式
 * 3. 主从
 * 4. 作为简单的消息队列
 */
@Api(tags = "Redis测试")
@RestController
@RequestMapping("/datasource")
@Slf4j
public class RedisController {

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/testString")
    @ApiOperation(value = "测试字符串")
    public Boolean testString() {
        redisTemplate.opsForValue().set("userName", "pan_junbiao的博客");
        redisTemplate.opsForValue().set("blogUrl", "https://blog.csdn.net/pan_junbiao");
        redisTemplate.opsForValue().set("blogRemark", "您好，欢迎访问 pan_junbiao的博客");
        log.info("用户名称：" + redisTemplate.opsForValue().get("userName"));
        log.info("博客地址：" + redisTemplate.opsForValue().get("blogUrl"));
        log.info("博客信息：" + redisTemplate.opsForValue().get("blogRemark"));

        //设置的是3s失效，3s之内查询有结果，3s之后返回null
        redisTemplate.opsForValue().set("blogRemark", "您好，欢迎访问 pan_junbiao的博客", 3, TimeUnit.SECONDS);
        try {
            Object s1 = redisTemplate.opsForValue().get("blogRemark");
            log.info("博客信息：" + s1);
            Thread.currentThread().sleep(2000);

            Object s2 = redisTemplate.opsForValue().get("blogRemark");
            log.info("博客信息：" + s2);
            Thread.currentThread().sleep(5000);

            Object s3 = redisTemplate.opsForValue().get("blogRemark");
            log.info("博客信息：" + s3);
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }

        return Boolean.TRUE;
    }


    @GetMapping("/testList")
    @ApiOperation(value="测试list（有序，可重复）  -  Redis列表是简单的字符串列表")
    public Boolean testList(){
        String[] user1 = new String[]{"1","博客","您好，欢迎访问博客"};
        String[] user2 = new String[]{"2","博客","https://blog.csdn.net/pan_junbiao"};
        String[] user3 = new String[]{"3","博客","您好，欢迎访问博客"};

        redisTemplate.opsForList().rightPushAll("user1",user1);
        redisTemplate.opsForList().rightPushAll("user2",user2);
        redisTemplate.opsForList().rightPushAll("user3",user3);

        log.info("result:{}" , redisTemplate.opsForList().range("user1",0,-1));
        log.info("result:{}" , redisTemplate.opsForList().range("user2",0,-1));
        log.info("result:{}" , redisTemplate.opsForList().range("user3",0,-1));

        String[] user = new String[]{"1","博客","您好，欢迎访问博客"};
        redisTemplate.opsForList().leftPushAll("user",user);
        log.info("列表的长度：" + redisTemplate.opsForList().size("user"));

        return Boolean.TRUE;
    }


    @GetMapping("/testHash")
    @ApiOperation(value="测试hash  - hash 特别适合用于存储对象。value 中存放的是结构化的对象")
    public Boolean testHash(){
        Map<String,Object> userMap = new HashMap<>(2);
        userMap.put("userName","博客");
        userMap.put("blogRemark","您好，欢迎访问博客");
        redisTemplate.opsForHash().putAll("userHash",userMap);
        log.info("result:{}" , redisTemplate.opsForHash().entries("userHash"));

        return Boolean.TRUE;
    }


    @GetMapping("/testSet")
    @ApiOperation(value="测试集合set - set 是存放不重复值的集合。利用 set 可以做全局去重复的功能。还可以进行交集、并集、差集等操作，" +
            "也可用来实现计算共同喜好、全部的喜好、自己独有的喜好等功能。Redis 的 set 是 string 类型的无序集合，通过散列表实现")
    public Boolean testSet(){
        String[] citys = new String[]{"北京","上海","广州","深圳"};
        log.info("result:{}" , redisTemplate.opsForSet().add("citySet",citys));
        log.info("result:{}" , redisTemplate.opsForSet().add("citySet","香港","澳门","台湾"));
        //返回集合中的所有元素
        log.info("result:{}" , redisTemplate.opsForSet().members("citySet"));

        return Boolean.TRUE;
    }


    @GetMapping("/testSortedSet")
    @ApiOperation(value="测试有序集合sorted-set zset（Sorted Set 有序集合）也是 string 类型元素的集合，且不允许重复的成员。每个元素都会关联一个 double 类型的分数。可以通过分数将该集合中的成员从小到大进行排序。" +
            "zset 的成员是唯一的，但权重参数分数（score）却可以重复。集合中的元素能够按 score 进行排列。它可以用来做排行榜应用、取TOP/N、延时任务、范围查找等。" +
            "版权声明：本文为CSDN博主「pan_junbiao」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。")
    public Boolean testSortedSet(){
        ZSetOperations.TypedTuple<String> objectTypedTuple1 = new DefaultTypedTuple<>("博客_01",9.6);
        ZSetOperations.TypedTuple<String> objectTypedTuple2 = new DefaultTypedTuple<>("博客_02",1.5);
        ZSetOperations.TypedTuple<String> objectTypedTuple3 = new DefaultTypedTuple<>("博客_03",7.4);

        Set<ZSetOperations.TypedTuple<String>> typeSet = new HashSet<ZSetOperations.TypedTuple<String>>();
        typeSet.add(objectTypedTuple1);
        typeSet.add(objectTypedTuple2);
        typeSet.add(objectTypedTuple3);

        log.info("result:{}" , redisTemplate.opsForZSet().add("typeSet",typeSet));
        log.info("result:{}" , redisTemplate.opsForZSet().range("typeSet",0,-1));

        return Boolean.TRUE;
    }


}